﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using InfoSvc.Data;
using InfoSvc.Data.WPP;
using Com.SharpZebra;
using Com.SharpZebra.Commands.Codes;
using Com.SharpZebra.Printing;
using System.Configuration;
using System.Collections.Generic;

namespace WPP_Console
{
    /// <summary>
    /// Interaction logic for OrderWindow.xaml
    /// </summary>
    public partial class OrderWindow : Window
    {
        public Order currentOrder;
        private MainWindow mainWindow;
        private List<Package> updatedPackages;
        private string cust_id;

        /// <summary>
        /// Getter for the order associated with the window
        /// </summary>
        public Order Order
        {
            get { return currentOrder; }
        }

        public string CustID
        {
            get { return cust_id; }
            set 
            { 
                cust_id = value;
                foreach (Package p in updatedPackages) p.CustomerIdentifier = cust_id;
            }
        }

        public OrderWindow()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Main Constructor. Initializes all of the fields at the top of
        /// the window to the data in the Order object.
        /// </summary>
        /// <param name="order"></param>
        /// <param name="parent"></param>
        public OrderWindow(Order order, MainWindow parent)
        {
            InitializeComponent();
            shippingNameLbl.Content = order.OrderShippingName;
            billingNameLbl.Content = order.OrderBillingName;
            telephoneLbl.Content = order.Phone;
            packageCountLbl.Content = order.Packages.Length;
            orderNumberLbl.Content = order.OrderNumber;
            createDateLbl.Content = order.OrderCreationDate.ToShortDateString();
            procDateLbl.Content = order.OrderProcessDate.ToShortDateString();
            if (order.OrderCompleteDate != null) compDateLbl.Content = order.OrderCompleteDate.Value.ToShortDateString();

            this.Title = "Order " + order.OrderNumber + " for " + order.OrderShippingName;

            currentOrder = order;

            buildPackageDataGrid();
            orderStatusLbl.Content = CheckOrderStatus();

            mainWindow = parent;

            updatedPackages = new List<Package>();
        }

        /// <summary>
        /// Populates the package data grid with the packages in the current
        /// order.
        /// </summary>
        public void buildPackageDataGrid()
        {
            PackageGrid.Columns.Clear();
            PackageGrid.Items.Clear();

            foreach (Package p in currentOrder.Packages)
            {
                if (p.Cancelled) p.PackageStatus = "Cancelled";
                else if (p.Complete) p.PackageStatus = "Picked-Up";
                else p.PackageStatus = "Not Picked-Up";

                if (p.PackagePickupDate == DateTime.MinValue) p.PackagePickupDate = null;
                if (p.PackageDateBoxed == DateTime.MinValue) p.PackageDateBoxed = null;

                string custIdDisp = "", state = null;
                if (p.CustomerIdentifier != "" && p.CustomerIdentifier != null) state = p.CustomerIdentifier.Substring(0, 2);
                if (state == null) custIdDisp = null;
                else if (state == "GS") custIdDisp += "Eagle ID: " + p.CustomerIdentifier.Substring(3);
                else custIdDisp += "Driver's License: " + p.CustomerIdentifier.Substring(3) + " (" + state + ")";

                PackageGrid.Items.Add(new Package() { PackageNumber = p.PackageNumber, PackagePickupDate = p.PackagePickupDate, PackageDateBoxed = p.PackageDateBoxed, PackageStatus = p.PackageStatus, CustomerIdentifier = custIdDisp });
            }

            DataGridTextColumn col2 = new DataGridTextColumn();
            col2.Binding = new Binding("PackageNumber");
            col2.Header = "PACKAGE NUMBER";
            col2.Width = new DataGridLength(0.2, DataGridLengthUnitType.Auto);
            DataGridTextColumn col3 = new DataGridTextColumn();
            col3.Binding = new Binding("PackagePickupDate");
            col3.Header = "DATE PICKED UP";
            col3.Width = new DataGridLength(0.2, DataGridLengthUnitType.Auto);
            DataGridTextColumn col4 = new DataGridTextColumn();
            col4.Binding = new Binding("PackageDateBoxed");
            col4.Header = "DATE BOXED";
            col4.Width = new DataGridLength(0.2, DataGridLengthUnitType.Auto);
            DataGridTextColumn col5 = new DataGridTextColumn();
            col5.Binding = new Binding("PackageStatus");
            col5.Header = "PACKAGE STATUS";
            col4.Width = new DataGridLength(0.2, DataGridLengthUnitType.Auto);
            DataGridTextColumn col6 = new DataGridTextColumn();
            col6.Binding = new Binding("CustomerIdentifier");
            col6.Header = "PICKED UP BY";
            col4.Width = new DataGridLength(0.2, DataGridLengthUnitType.Star);
            
            PackageGrid.Columns.Add(col2);
            PackageGrid.Columns.Add(col3);
            PackageGrid.Columns.Add(col4);
            PackageGrid.Columns.Add(col5);
            PackageGrid.Columns.Add(col6);
            
            PackageGrid.IsReadOnly = true;
        }

        /// <summary>
        /// Builds the order item data grid with the package that was passed in.
        /// </summary>
        /// <param name="package">the package containing the order items to populate the data grid with.</param>
        private void buildOrderItemDataGrid(Package package)
        {
            ItemGrid.Columns.Clear();
            ItemGrid.Items.Clear();

            foreach (OrderItem o in package.OrderItems)
            {
                ItemGrid.Items.Add(o); 
            }

            DataGridTextColumn col1 = new DataGridTextColumn();
            col1.Binding = new Binding("ItemPossku");
            col1.Header = "POSSKU";
            col1.Width = new DataGridLength(0.25, DataGridLengthUnitType.Auto);
            DataGridTextColumn col2 = new DataGridTextColumn();
            col2.Binding = new Binding("ItemDescription");
            col2.Header = "ITEM DESCRIPTION";
            col2.Width = new DataGridLength(0.25, DataGridLengthUnitType.Star);
            DataGridTextColumn col3 = new DataGridTextColumn();
            col3.Binding = new Binding("ItemCustomerNotes");
            col3.Header = "CUSTOMER NOTES";
            col3.Width = new DataGridLength(0.25, DataGridLengthUnitType.Auto);
            DataGridTextColumn col4 = new DataGridTextColumn();
            col4.Binding = new Binding("ItemQuantity");
            col4.Header = "QUANTITY";
            col4.Width = new DataGridLength(0.25, DataGridLengthUnitType.Auto);

            ItemGrid.Columns.Add(col1);
            ItemGrid.Columns.Add(col2);
            ItemGrid.Columns.Add(col3);
            ItemGrid.Columns.Add(col4);

            ItemGrid.IsReadOnly = true;
        }

        /// <summary>
        /// Event handler for the cancel button. Re-executes the search upon returning to the MainWindow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
            mainWindow.ExecuteSearch();
        }

        /// <summary>
        /// Sends the Order information through Zebra commands to the printer.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void print_Click(object sender, RoutedEventArgs e)
        {
            if (ConfigurationManager.AppSettings["printer_name"].ToString() == "")
            {
                PrintSettingsWindow psw = new PrintSettingsWindow();
                psw.Show();
            }

            if (PackageGrid.SelectedIndex < 0)
            {
                MessageBox.Show("Please select a package or check \"Print labels for all packages\".");
                return;
            }
            int x = 0, y = 0;

            string firstname = currentOrder.OrderBillingName.Substring(0, currentOrder.OrderBillingName.IndexOf(' '));
            string lastname = currentOrder.OrderBillingName.Substring(currentOrder.OrderBillingName.IndexOf(' ') + 1, currentOrder.OrderBillingName.Length - 1 - currentOrder.OrderBillingName.IndexOf(' '));
            string packagenumbarcode = currentOrder.Packages[PackageGrid.SelectedIndex].PackageNumber;
            string orderbarcode = currentOrder.OrderNumber;
            string pickupname = currentOrder.OrderShippingName;
            string phonenumber = currentOrder.Phone;
            string processdate = currentOrder.OrderProcessDate.ToString();

            ZebraCommands zc = new ZebraCommands();
            zc.Add(ZebraCommands.DrawBox(x + 645, y + 1, 3, x + 800, y + 315));
            zc.Add(ZebraCommands.TextCommand(x + 790, y + 10, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 6, 9, false, Trun(firstname, 2)));
            zc.Add(ZebraCommands.TextCommand(x + 795, y + 335, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 4, 4, false, Trun(lastname, 14)));
            zc.Add(ZebraCommands.TextCommand(x + 700, y + 335, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 4, 4, false, Trun(firstname, 14)));
            zc.Add(ZebraCommands.BarCodeCommand(x + 590, y + 10, ElementRotation.ROTATE_90_DEGREES, 3, 2, 7, 60, true, packagenumbarcode));
            zc.Add(ZebraCommands.BarCodeCommand(x + 480, y + 10, ElementRotation.ROTATE_90_DEGREES, 3, 2, 7, 60, true, orderbarcode));
            zc.Add(ZebraCommands.TextCommand(x + 375, y + 10, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 3, 3, false, "Customer Name:"));
            zc.Add(ZebraCommands.TextCommand(x + 285, y + 50, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 3, 3, false, pickupname));
            zc.Add(ZebraCommands.TextCommand(x + 185, y + 50, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 3, 3, false, "Tel:"));
            zc.Add(ZebraCommands.TextCommand(x + 185, y + 230, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 3, 3, false, phonenumber));
            zc.Add(ZebraCommands.TextCommand(x + 115, y + 50, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 2, 2, false, "Process Date:"));
            zc.Add(ZebraCommands.TextCommand(x + 115, y + 465, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 2, 2, false, processdate));
            new ZebraPrinter(ConfigurationManager.AppSettings["printer_name"].ToString()).Print(zc);
        }

        /// <summary>
        /// Updates the selected package when a user clicks a different row in the
        /// package datagrid.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PackageGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            int selectedPackage = PackageGrid.SelectedIndex;
            if (selectedPackage >= 0) buildOrderItemDataGrid(currentOrder.Packages[selectedPackage]);
        }

        /// <summary>
        /// Marks a single package as complete.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void markCompleteBtn_Click(object sender, RoutedEventArgs e)
        {
            int selectedPackage = PackageGrid.SelectedIndex;
            if (selectedPackage >= 0)
            {
                Package SelectedPackage = currentOrder.Packages[selectedPackage];
                if (SelectedPackage != null)
                {
                    SelectedPackage.Complete = true;
                    updatedPackages.Add(SelectedPackage);
                    buildPackageDataGrid();
                }
                orderStatusLbl.Content = CheckOrderStatus();
            }
        }

        //UNIT TEST
        private string CheckOrderStatus()
        {
            bool cancelled = true;
            bool complete = true;
            foreach(Package p in currentOrder.Packages)
            {
                if (!p.Cancelled) cancelled = false;
                if (!p.Complete) complete = false;
                if (p.PackageStatus == "Picked-Up" || p.PackageStatus == "Cancelled") complete = true;
                else complete = false;
            }
            if (cancelled) 
            {
                currentOrder.Cancelled = true;
                return "Cancelled";
            }
            else if (complete)
            {
                currentOrder.Complete = true;
                currentOrder.OrderCompleteDate = DateTime.Now;
                return "Picked-Up";
            }
            else
            {
                return "Not Picked-Up";
            }
        }

        /// <summary>
        /// Sends the updated order to the service.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SaveOrder_Click(object sender, RoutedEventArgs e)
        {
            CustomerIdentification ci = new CustomerIdentification(this);
            ci.Show();
        }

        public void CommitChanges()
        {
            InvokeResponse ir = ServiceClient.UpdateOrder(currentOrder);
            if (ir.ResponseCode == 0) MessageBox.Show("Order was successfully updated!");
            else MessageBox.Show("An Error Occurred with Status Code: " + ir.ResponseCode + "\nPlease try again. If this error persists, please contact your System Administrator.");
        }

        /// <summary>
        /// Trucates a string to a specified length.
        /// </summary>
        /// <param name="source">The String to be truncated.</param>
        /// <param name="length">The length at which to truncate.</param>
        /// <returns>The truncated string.</returns>
        public static string Trun(string source, int length)
        {
            if (source.Length > length)
            {
                source = source.Substring(0, length);
            }
            return source;
        }

        /// <summary>
        /// Event handler for the mark all complete button.
        /// Simple loops through each package and marks it as complete
        /// then updates the datagrid.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void markAllCompleteBtn_Click(object sender, RoutedEventArgs e)
        {
            foreach (Package p in currentOrder.Packages)
            {
                p.Complete = true;
                updatedPackages.Add(p);
            }
            buildPackageDataGrid();
            orderStatusLbl.Content = CheckOrderStatus();
        }

        private void printAll_Click(object sender, RoutedEventArgs e)
        {
            if (ConfigurationManager.AppSettings["printer_name"].ToString() == "")
            {
                PrintSettingsWindow psw = new PrintSettingsWindow();
                psw.Show();
            }

            foreach (Package p in currentOrder.Packages)
            {
                int x = 0, y = 0;

                string firstname = currentOrder.OrderBillingName.Substring(0, currentOrder.OrderBillingName.IndexOf(' '));
                string lastname = currentOrder.OrderBillingName.Substring(currentOrder.OrderBillingName.IndexOf(' ') + 1, currentOrder.OrderBillingName.Length - 1 - currentOrder.OrderBillingName.IndexOf(' '));
                string packagenumbarcode = p.PackageNumber;
                string orderbarcode = currentOrder.OrderNumber;
                string pickupname = currentOrder.OrderShippingName;
                string phonenumber = currentOrder.Phone;
                string processdate = currentOrder.OrderProcessDate.ToString();

                ZebraCommands zc = new ZebraCommands();
                zc.Add(ZebraCommands.DrawBox(x + 645, y + 1, 3, x + 800, y + 315));
                zc.Add(ZebraCommands.TextCommand(x + 790, y + 10, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 6, 9, false, Trun(firstname, 2)));
                zc.Add(ZebraCommands.TextCommand(x + 795, y + 335, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 4, 4, false, Trun(lastname, 14)));
                zc.Add(ZebraCommands.TextCommand(x + 700, y + 335, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 4, 4, false, Trun(firstname, 14)));
                zc.Add(ZebraCommands.BarCodeCommand(x + 590, y + 10, ElementRotation.ROTATE_90_DEGREES, 3, 2, 7, 60, true, packagenumbarcode));
                zc.Add(ZebraCommands.BarCodeCommand(x + 480, y + 10, ElementRotation.ROTATE_90_DEGREES, 3, 2, 7, 60, true, orderbarcode));
                zc.Add(ZebraCommands.TextCommand(x + 375, y + 10, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 3, 3, false, "Customer Name:"));
                zc.Add(ZebraCommands.TextCommand(x + 285, y + 50, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.LARGE, 3, 3, false, pickupname));
                zc.Add(ZebraCommands.TextCommand(x + 185, y + 50, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 3, 3, false, "Tel:"));
                zc.Add(ZebraCommands.TextCommand(x + 185, y + 230, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 3, 3, false, phonenumber));
                zc.Add(ZebraCommands.TextCommand(x + 115, y + 50, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 2, 2, false, "Process Date:"));
                zc.Add(ZebraCommands.TextCommand(x + 115, y + 465, ElementRotation.ROTATE_90_DEGREES, StandardZebraFont.SMALL, 2, 2, false, processdate));
                new ZebraPrinter(ConfigurationManager.AppSettings["printer_name"].ToString()).Print(zc);
            }
        }
    }
}
